///枚举
//Rust有一个集合类型，称为枚举 (enum)，代表一系列子数据类型的集合。 其中子数据结构可以为空-如果全部子数据结构都是空的，
// 就等价于C语言中的enum。 我们需要使用::来获得每个元素的名称。
//枚举
#[derive(Debug, Clone, Copy)]
enum IP {
    V4(u8, u8, u8), //为枚举类成员添加元组属性
    V6
}



//为枚举定义方法
impl IP {
    fn show(&self){
        println!("{:?}", self );
    }
}


enum Msg {
    NumericInputChanged(Option<u32>),

}



fn show_enum1<F: Fn(Option<u32>) -> Msg + 'static>(f:F){
    let m = f(Some(1));
    match m {
        Msg::NumericInputChanged(Some(x)) => println!("{}", x),
        Msg::NumericInputChanged(None) => println!("None"),
    }
}
fn show_enum2<F>(f:F) where F: Fn(Option<u32>) -> Msg + 'static{
    let m = f(Some(2));
    match m {
        Msg::NumericInputChanged(Some(x)) => println!("{}", x),
        Msg::NumericInputChanged(None) => println!("None"),
    }
}

fn show_enum3(f: impl Fn(Option<u32>) -> Msg + 'static){
    let m = f(Some(3));
    match m {
        Msg::NumericInputChanged(Some(x)) => println!("{}", x),
        Msg::NumericInputChanged(None) => println!("None"),
    }
}


#[test]
pub fn test_show_enum(){
    //枚举实现了 Fn(Option<u32>) -> Msg + 'static
    show_enum1(Msg::NumericInputChanged);
    show_enum2(Msg::NumericInputChanged);
    show_enum3(Msg::NumericInputChanged);
   
}

#[test]
pub fn enum_demo(){
    let v4 = IP::V4(2, 3, 4);
    let v6 = IP::V6;
    println!("{:?}", v4);
    println!("{:?}", v6);

    v4.show();
    v6.show();

    match v4 {
        IP::V4(u1, u2, u3) => {
            println!("{}, {}, {}", u1, u2, u3)
        },
        IP::V6 =>{

        }
    }
}

//Option枚举,Option 是 Rust 标准库中的枚举类，这个类用于填补 Rust 不支持 null 引用的空白

#[test]
pub fn option_demo(){
    //如果你想定义一个可以为空值的类，你可以这样：
    let opt: Option<&str>  = Option::Some("hello");
    match opt {
        Option::Some(something) => {
            println!("{}", something);
        },
        Option::None => {
            println!("opt is none");
        }
    }
}
//match,match必须穷举所有的结果，可以用 _ 下划线通配符（必须放在最后）表示其他所有

enum Coin{
    Penny,
    Nickel,
    Dime,
    Quarter,
}
fn value_in_cents(coin: Coin) ->u8 {
//    return match coin {
//         Coin::Penny => {return 1;},
//         Coin::Nickel => {return 5;},
//         Coin::Dime => 10,
//         Coin::Quarter => 25,
//     };

    match coin {
        Coin::Penny => {return 1;},
        Coin::Nickel => {return 5;},
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

pub fn match_demo(){
    let v : u8 = value_in_cents(Coin::Nickel);
    println!("{}", v);
}
